#include "TwOgrePosition3DVariable.h"

#include <sstream>

#include "TwOgreWindow.h"
#include "TwOgreWindowManager.h"

namespace TwOgre{
    
    Position3DVariable::Position3DVariable(Window *parent, const Ogre::String& name, bool readOnly, const Ogre::String& label, 
		Ogre::Vector3 value, const Ogre::String& groupName, const Ogre::String& help) :
		Variable(parent, name, TW_TYPE_UNDEF), mValue(value)
	{
		mSVectorValue = SVector3(mValue.x, mValue.y, mValue.z);
        
        TwType TW_TYPE_VECTOR3;
        
        SVector3 elem;
 
        TwStructMember SVector3StructMembers[] = {
            { "x", TW_TYPE_FLOAT, offsetof(SVector3, X)},
            { "y", TW_TYPE_FLOAT, offsetof(SVector3, Y)},
            { "z", TW_TYPE_FLOAT, offsetof(SVector3, Z)}
        };
        
        TW_TYPE_VECTOR3 = TwDefineStruct("TW_TYPE_VECTOR3", SVector3StructMembers, 3, sizeof(SVector3), NULL, NULL);
		
		if(readOnly)
		{
			TwAddVarRO(mParent->getTweakBar(), mName.c_str(), TW_TYPE_VECTOR3, &mSVectorValue, "");
		}
		else
		{
			TwAddVarRW(mParent->getTweakBar(), mName.c_str(), TW_TYPE_VECTOR3, &mSVectorValue, "");
		}

		if(label.compare("") != 0)
		{
			setLabel(label);
		}
		if(groupName.compare("") != 0)
		{
			setGroup(groupName);
		}
		if(help.compare("") != 0)
		{
			setHelp(help);
		}
	}

	Position3DVariable::Position3DVariable(Position3DParams& params) :
        Variable(params.parent_, params.name_, params.type_), mValue(params.value_)
    {
		mSVectorValue = SVector3(mValue.x, mValue.y, mValue.z);

        TwType TW_TYPE_VECTOR3;
        
        SVector3 elem;
 
        TwStructMember SVector3StructMembers[] = {
            { "x", TW_TYPE_FLOAT, offsetof(SVector3, X), Ogre::String(" precision=" + Ogre::StringConverter::toString(params.precision_) + " ").c_str() },
            { "y", TW_TYPE_FLOAT, offsetof(SVector3, Y), Ogre::String(" precision=" + Ogre::StringConverter::toString(params.precision_) + " ").c_str()},
            { "z", TW_TYPE_FLOAT, offsetof(SVector3, Z), Ogre::String(" precision=" + Ogre::StringConverter::toString(params.precision_) + " ").c_str()}
        };
        
        TW_TYPE_VECTOR3 = TwDefineStruct("TW_TYPE_VECTOR3", SVector3StructMembers, 3, sizeof(SVector3), NULL, NULL);
        
        if((params.getCB_ != NULL) && (params.setCB_ != NULL) && (params.data_ != NULL))
        {
            TwAddVarCB(mParent->getTweakBar(), mName.c_str(), TW_TYPE_VECTOR3, params.setCB_, params.getCB_, params.data_, "");
        }
        else
        {
		    if(params.readOnly_)
		    {
                TwAddVarRO(mParent->getTweakBar(), mName.c_str(), TW_TYPE_VECTOR3, &mSVectorValue, "");
		    }
		    else
		    {
                TwAddVarRW(mParent->getTweakBar(), mName.c_str(), TW_TYPE_VECTOR3, &mSVectorValue, "");
		    }
        }
		
        if(params.label_.compare("") != 0)
		{
			setLabel(params.label_);
		}
		if(params.group_.compare("") != 0)
		{
			setGroup(params.group_);
		}
		if(params.help_.compare("") != 0)
		{
			setHelp(params.help_);
		}
        
    }
	
    Position3DVariable::~Position3DVariable()
	{
		TwRemoveVar(mParent->getTweakBar(), mName.c_str());
	}

	Ogre::Vector3 Position3DVariable::getVector3Value() const
	{
		mValue = Ogre::Vector3(mSVectorValue.X, mSVectorValue.Y, mSVectorValue.Z);
		return mValue;
	}

	void Position3DVariable::setVector3Value(Ogre::Vector3 value)
	{
		mValue = value;
		mSVectorValue = SVector3(mValue.x, mValue.y, mValue.z);
	}

}; // End Namespace
